package com.lijiajia.cloud.authserver.configuration.security;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutHandler;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

/**
 * @author lijiajia
 * @since 2019-4-3
 */
@Configuration
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
    private final UserDetailsService usernameUserService;
    private final OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService;
    private final PersistentTokenRepository tokenRepository;
    private final PasswordEncoder userPasswordEncoder;
    private final AuthenticationSuccessHandler successHandler;
    private final AuthenticationFailureHandler failureHandler;
    private final LogoutHandler logLogoutHandler;


    public SecurityConfigurer(@Qualifier("usernameUserService") UserDetailsService usernameUserService,
                              @Qualifier("customOAuth2UserService") OAuth2UserService<OAuth2UserRequest, OAuth2User> oAuth2UserService,
                              PersistentTokenRepository tokenRepository,
                              @Qualifier("userPasswordEncoder") PasswordEncoder userPasswordEncoder,
                              AuthenticationSuccessHandler successHandler,
                              AuthenticationFailureHandler failureHandler,
                              @Qualifier("logLogoutHandler") LogoutHandler logoutHandler
                              // ,
                              // @Qualifier("logAuthenticationEventPublisher") AuthenticationEventPublisher authenticationEventPublisher
    ) {
        this.usernameUserService = usernameUserService;
        this.oAuth2UserService = oAuth2UserService;
        this.tokenRepository = tokenRepository;
        this.userPasswordEncoder = userPasswordEncoder;
        this.successHandler = successHandler;
        this.failureHandler = failureHandler;
        this.logLogoutHandler = logoutHandler;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(usernameUserService)
                .passwordEncoder(userPasswordEncoder);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .mvcMatchers(HttpMethod.OPTIONS, "/**")
                .antMatchers("/", "/actuator", "/actuator/*");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .cors().disable()
                .formLogin()
                .successHandler(successHandler)
                .failureHandler(failureHandler)

                .and().oauth2Login()
                .userInfoEndpoint()
                .userService(oAuth2UserService)
                .and()
                .successHandler(successHandler)
                .failureHandler(failureHandler)

                .and().rememberMe()
                .tokenRepository(tokenRepository)
                .userDetailsService(usernameUserService)

                .and().logout()
                .addLogoutHandler(logLogoutHandler)

                .and().authorizeRequests()
                .antMatchers("/user").authenticated();
    }
}
